<?php
/**
 *
 * Enter description here ...
 * @author chienvh
 *
 */

class TreeComponent extends Object {

    // Lưu cây vào biến này
    var $nodes = array();
    var $nodeIdsByOrder = array();
    var $nodesPvByOrder = array();
    var $totalPv = 0;

    /**
     *
     * Enter description here ...
     * @param $controller
     * @param $settings
     */
    function initialize(&$controller, $settings = array()) {
        // saving the controller reference for later use
        $this->controller =& $controller;
        if ($this->importConfigFromDatabase()==false){
            $this->importConfigDefault();
        }
    }

    /**
     * Tính toán thông tin cho toàn bộ hệ thống
     * Chức năng này dùng cho kế toán công ty
     */
    function calculateCompany(){
        set_time_limit(0);
        $this->importMemberFromDatabase();
        $this->calculateGroupPv();
        $this->calculateLevel();
        $this->calculateDirectCommission();
        $this->calculateIndirectCommission();
        $this->calculateLeadCommission();
        $this->calculateGlobalCommission();
        $this->calculatePersonalIncomeTax();
    }

    
    /**
     * Tính toán thông tin cho toàn bộ hệ thống
     * Chức năng này dùng cho kế toán công ty
     */
    function calculateForMember($node){
        set_time_limit(0);
        $this->importMemberFromDatabase();
        $this->calculateGroupPv();
        $this->calculateLevel();
        $this->calculateDirectCommissionForOneMember($node);
        $this->calculateIndirectCommissionForOneMember($node);
        $this->calculateLeadCommissionForOneMember($node);
        $this->calculateGlobalCommissionForOneMember($node);
        $this->calculatePersonalIncomeTaxForOneMember($node);
    }

    /**
     * Cập nhật level và tổng tích lũy cá nhân
     */
    function updateMemberInfo(){
        foreach ($this->nodes as $node){
            $member = $this->controller->Member->findById($node['id']);

            $personalPv = $member['Member']['personal_pv'];
            $personalPv += $node['personal_pv'];

            $member['Member']['personal_pv'] = $personalPv;
            $member['Member']['levels'] = $node['tmp_levels'];

            $this->controller->Member->save($member, array('validate' => false));
        }
    }

    /**
     * Tính toán lại levels
     */
    function calculateLevel(){
//        $this->nodeIdsByOrder = array();
//
//        // Lấy danh sách tree theo thứ tự duyệt cây chiều rộng
//        $queued = array();
//        foreach ($this->nodes as $node){
//            if ($node['parent_id'] == 0){
//                array_push($queued, $node);
//            }
//        }
//        while (count($queued)>0){
//            $node = array_shift($queued);
//            $this->nodeIdsByOrder[] = $node['id'];
//             
//            $childNodes = $this->getChildNodes($node);
//            foreach ($childNodes as $childNode){
//                array_push($queued, $childNode);
//            }
//        }

        // Tính levels theo thuật toán quy hoạch động
        $i = count($this->nodeIdsByOrder) - 1;
        while ($i>=0){
            $node = &$this->nodes[$this->nodeIdsByOrder[$i]];

            // Tính toán level
            $this->nodes[$this->nodeIdsByOrder[$i]]['tmp_levels'] = $this->getLevel($node);
            $i -= 1;
        }
    }
    
    /**
     * Tính toán level mới cho member
     */
    function getLevel($node){
        // Genneral Leader
        if ($node['levels']>=6 && $this->isForeverLead($node)){
            return 15;
        }

        // Genneral Leader
        if ($node['levels']>=6 && $this->isGeneralLead($node)){
            return 14;
        }
        
        // Từ vip1 đến supper lead
        if ($node['levels']>=6 && $this->getVip1ToSupperLead($node)!=false){
            return $this->getVip1ToSupperLead($node);
        }
        
        // Lead 6
        if ($node['levels']<6 && $this->isLead6($node)){
            return 6;
        }
        
        // Lead 5
        if ($node['levels']<5 && $this->isLead5($node)){
            return 5;
        }
        
        // Lead 4
        if ($node['levels']<4 && $this->isLead4($node)){
            return 4;
        }
        
        // Lead 3
        if ($node['levels']<3 && $this->isLead3($node)){
            return 3;
        }
        
        // Lead 2
        if ($node['levels']<2 && $this->isLead2($node)){
            return 2;
        }
        
        // Lead 1
        if ($node['levels']<1 && $this->isLead1($node)){
            return 1;
        }
        
        return $node['levels'];
    }

    /**
     * Kiểm tra có phải là lead1 hay không ?
     */
    function isLead1($node){
        if ($node['levels']<1){
            if ($this->nodes[$node['id']]['personal_pv'] >= 50){
                return true;
            }
        }
        return false;
    }

    /**
     *
     * Kiểm tra có phải là lead2 hay không?
     * @param $node
     */
    function isLead2($node){
        // Trường hợp dự bị, mua một lần 250
        if ($node['levels'] == 0){
            if (isset($this->nodes[$node['id']]['max_pv_per_invoice']) && $this->nodes[$node['id']]['max_pv_per_invoice'] >= 250){
                return true;
            } else {
                return false;
            }
        }
        
        // Trường hợp đã là lead 1 có tổng pv cá nhân >=250
        if ($node['levels'] == 1 && $this->nodes[$node['id']]['personal_pv'] >= 250){
            return true;
        }
        
        $childNodes = $this->getChildNodes($node);
        $numChidldrenOfLead1 = 0;
        foreach ($childNodes as $childNode){
            if ($childNode['tmp_levels']==1){
                $numChidldrenOfLead1 += 1;
            }
        }
        
        // Điều kiện 2 dây lead 1, tổng tích lũy nhóm là 1000pv
        if ($numChidldrenOfLead1>=2 && $this->nodes[$node['id']]['group_pv']>1000){
            return true;
        }
        
        // Điều kiện 3 dây lead 1 mỗi dây tích lũy 500pv        
        if ($numChidldrenOfLead1>=3 && $this->nodes[$node['id']]['group_pv']>500){
            return true;
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là lead3 không
     * @param $node
     */
    function isLead3($node){
        // Trường hợp dự bị, mua một lần 1000
        if ($node['levels'] == 0){
            if (isset($this->nodes[$node['id']]['max_pv_per_invoice']) && $this->nodes[$node['id']]['max_pv_per_invoice'] >= 1000){
                return true;
            } else {
                return false;
            }
        }
        
        // Trường hợp leader 1, tích lũy cá nhân là 1000
        if ($node['levels'] == 1){
            if ($this->nodes[$node['id']]['personal_pv'] >= 1000){
                return true;
            } else {
                return false;
            }
        }
        
        if ($node['levels'] == 2){
            if ($this->nodes[$node['id']]['personal_pv'] >= 1000){
                return true;
            }
            
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfLead2 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']==2){
                    $numChidldrenOfLead2 += 1;
                }
            }
            
            // Trường hợp . 3 dây Leader 2 tổng tích lũy 1250 PV
            if ($numChidldrenOfLead2>=3 && $this->nodes[$node['id']]['group_pv']>1250){
                return true;
            }
    
            // Trường hợp . 3 dây Leader 2 tổng tích lũy 1250 PV
            if ($numChidldrenOfLead2>=2 && $this->nodes[$node['id']]['group_pv']>1250){
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là lead4 không
     * @param $node
     */
    function isLead4($node){
        if ($node['levels'] == 3){
            // Đếm số leader 3
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfLead3 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']==3){
                    $numChidldrenOfLead3 += 1;
                }
            }
            
            // Trường hợp . 3 dây Leader 3 tổng tích lũy 5000 PV
            if ($numChidldrenOfLead3>=3 && $this->nodes[$node['id']]['group_pv']>5000){
                return true;
            }
    
            // Trường hợp . 3 dây Leader 3 tổng tích lũy 10000 PV
            if ($numChidldrenOfLead3>=2 && $this->nodes[$node['id']]['group_pv']>1250){
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là lead5 không
     * @param $node
     */
    function isLead5($node){
        if ($node['levels'] == 3 || $node['levels'] == 4){
            // Đếm số leader 3 và leader 4
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfLead3 = 0;
            $numChidldrenOfLead4 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']==3){
                    $numChidldrenOfLead3 += 1;
                }
                if ($childNode['tmp_levels']==4){
                    $numChidldrenOfLead4 += 1;
                }
            }
            
            // Trường hợp .3 dây leader 4 tích lũy 20.000
            if ($numChidldrenOfLead4>=3 && $this->nodes[$node['id']]['group_pv']>=20000){
                return true;
            }
    
            // Trường hợp . 2 dây leader 4, 3 dây leader 3 tích lũy 20.000
            if ($numChidldrenOfLead4>=2 && $numChidldrenOfLead3>=2 && $this->nodes[$node['id']]['group_pv']>=20000){
                return true;
            }
            
            // Trường hợp . 1 dây leader 4 + 5 dây leader 3 tích lũy 20.000
            if ($numChidldrenOfLead4>=1 && $numChidldrenOfLead3>=5 && $this->nodes[$node['id']]['group_pv']>=20000){
                return true;
            }
            
            // Trường hợp . 2 dây leader 4 tích lũy 40.000
            if ($numChidldrenOfLead4>=1 && $this->nodes[$node['id']]['group_pv']>=40000){
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là lead 6 không
     * @param $node
     */
    function isLead6($node){
        if ($node['levels'] == 3 || $node['levels'] == 4 || $node['levels'] == 5){
            // Đếm số leader 4 và leader 5
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfLead4 = 0;
            $numChidldrenOfLead5 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']==4){
                    $numChidldrenOfLead4 += 1;
                }
                if ($childNode['tmp_levels']==5){
                    $numChidldrenOfLead5 += 1;
                }
            }
            
            // Trường hợp 3 dây leader 5 tích lũy 80.000
            if ($numChidldrenOfLead5>=3 && $this->nodes[$node['id']]['group_pv']>=80000){
                return true;
            }
            
            // Trường hợp 2 dây leader 5, 3 dây leader 4 tích lũy 80.000
            if ($numChidldrenOfLead5>=2 && $numChidldrenOfLead4>=3 && $this->nodes[$node['id']]['group_pv']>=80000){
                return true;
            }
            
            // Trường hợp 1 dây leader 5 + 5 dây leader 4 tích lũy 80000
            if ($numChidldrenOfLead5>=1 && $numChidldrenOfLead4>=5 && $this->nodes[$node['id']]['group_pv']>=80000){
                return true;
            }
            
            // Trường hợp 2 dây leader 5 tích lũy 160.000
            if ($numChidldrenOfLead5>=2 && $this->nodes[$node['id']]['group_pv']>=160000){
                return true;
            }
        }
        
        return false;
    } 
    
    /**
     * 
     * Kiểm tra có phải là lead 7 - Vip leader 1 không
     * @param $node
     */
    function getVip1ToSupperLead($node){
        if ($node['levels'] >= 6){
            // Đếm số leader 6
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfLead6 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']>=6){
                    $numChidldrenOfLead6 += 1;
                }
            }
            
            // Trường hợp Vip leader 1:2 dây Leader 6 
            if ($numChidldrenOfLead6>=2){return 7;}
            
            // Trường hợp Vip leader 2:3 dây Leader 6 
            if ($numChidldrenOfLead6>=3){return 8;}
            
            // Trường hợp Vip leader 3:4 dây Leader 6 
            if ($numChidldrenOfLead6>=4){return 9;}
            
            // Trường hợp Vip Saphia Leader:5 dây Leader 6 
            if ($numChidldrenOfLead6>=5){return 10;}
            
            // Trường hợp Ruby Leader:6 dây Leader 6 
            if ($numChidldrenOfLead6>=6){return 11;}
            
            // Trường hợp Diamond Leader:7 dây Leader 6 
            if ($numChidldrenOfLead6>=7){return 12;}
            
            // Trường hợp Super Leader:8 dây Leader 6 
            if ($numChidldrenOfLead6>=8){return 13;}
            
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là General Leader 
     * @param $node
     */
    function isGeneralLead($node){
        if ($node['levels'] >= 6){
            // Đếm số leader 6
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfVipLead3 = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']>=9){
                    $numChidldrenOfVipLead3 += 1;
                }
            }
            
            // Trường hợp General Leader :3 dây Vip Leader 3 
            if ($numChidldrenOfVipLead3>=3){return true;}
        }
        
        return false;
    }
    
    /**
     * 
     * Kiểm tra có phải là General Leader 
     * @param $node
     */
    function isForeverLead($node){
        if ($node['levels'] >= 6){
            // Đếm số leader 6
            $childNodes = $this->getChildNodes($node);
            $numChidldrenOfVipLead3 = 0;
            $numChidldrenOfGeneralLead = 0;
            foreach ($childNodes as $childNode){
                if ($childNode['tmp_levels']>=9){
                    $numChidldrenOfVipLead3 += 1;
                }
                if ($childNode['tmp_levels']>=9){
                    $numChidldrenOfVipLead3 += 1;
                }
            }
            
            // Trường hợp General Leader :3 dây Vip Leader 3 
            if ($numChidldrenOfVipLead3>=3){return true;}
        }
        
        return false;
    }
    
    /**
     * Lấy giá trị config từ database
     * Enter description here ...
     */
    function importConfigFromDatabase(){
        $history = $this->controller->History->findByMonth("00-0000");
        
        if (!isset($history['History']['data'])){
            return false;
        }
        $config = json_decode($history['History']['data'], true);
        
        $this->directCommission = $config['DirectCommission'];
        $this->indirectCommission = $config['IndirectCommission'];
        $this->leadCommission= $config['LeadCommission'];
        $this->globalCommission = $config['GlobalCommission'];
        return true;
    }
    
    /**
     * Lấy giá trị config mặc định
     * Enter description here ...
     */
    function importConfigDefault(){
        /**
         * Tỉ lệ phần trăm hoa hồng trực tiếp
         * $directCommission[x] hoa hồng trực tiếp cấp x
         */
        $this->directCommission = array(
        0=>5,1=>15,2=>18,3=>22,4=>26,5=>30,6=>35,7=>35,8=>35,9=>35,10=>35,11=>35,12=>35,13=>35,14=>35,15=>35,
        );
    
        /**
         * Tỉ lệ hoa hồng gián tiếp
         * $indirectCommission[x][y] hoa hồng gián tiếp cấp x->y
         */
        $this->indirectCommission = array(
        1 => array(0 => 10,),
        2 => array(0 => 13, 1 => 3,),
        3 => array(0 => 17, 1 => 7, 2 => 4,),
        4 => array(0 => 21, 1 => 11, 2 => 8, 3 => 4,),
        5 => array(0 => 25, 1 => 15, 2 => 12, 3 => 8, 4 => 4,),
        6 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        7 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        8 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        9 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        10 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        11 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        12 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        13 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        14 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        15 => array(0 => 30, 1 => 20, 2 => 17, 3 => 13, 4 => 9, 5 => 5,),
        );
    
        /**
         * Tỉ lệ hoa hồng lãnh đạo
         * $indirectCommission[x][y] hoa hồng gián tiếp cấp x->y
         */
        $this->leadCommission = array(
        3 => array(0 => 1, 1 => 0.75,),
        4 => array(0 => 1.5, 1 => 0.75, 2 => 0.5,),
        5 => array(0 => 1.75, 1 => 1.5, 2 => 1, 3 => 0.75,),
        6 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        7 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        8 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        9 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        10 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        11 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        12 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        13 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        14 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        15 => array(0 => 2, 1 => 1.5, 2 => 1, 3 => 0.75, 4 => 0.75, 5 => 0.5, 6 => 0.5, 7 => 0.5,),
        );
    
        /**
         * Tỉ lệ hoa hồng toàn cầu
         * $globalCommission[x]hoa hồng toàn cầu cấp x
         */
        $this->globalCommission = array(7=>1,8=>0.75,9=>0.5,10=>0.5,11=>0.5,12=>0.5,13=>0.5,14=>0.25);
    }
    
    /**
     *
     * Đưa dữ liệu database vào
     */
    function importMemberFromDatabase(){
        $id_user = $this->controller->Session->read("tkid");
        $members = $this->controller->Member->find('all',
        array(
                'fields'=>"id, lft, rght, parent_id, name, user, levels, personal_pv, tax_code", 
                'conditions'=>array('Member.type'=>0),
                'order'=>'Member.parent_id',
        )
        );
        foreach ($members as &$member){
            $member['Member']['total_personal_pv'] = $member['Member']['personal_pv'];
            $member['Member']['personal_pv'] = 0;
            $this->nodes[$member['Member']['id']] = $member['Member'];
        }
        
        // Tạo mảng chưa con của tất cả các thành viên
        $children = array();
        foreach ($this->nodes as $node){
            if (isset($children[$node['parent_id']])){
                $children[$node['parent_id']][] = $node['id'];
            } else {
                $children[$node['parent_id']]= array($node['id']);
            }
        }
        foreach ($this->nodes as $node){
            if (isset($children[$node['id']])){
                $this->nodes[$node['id']]['children'] = json_encode($children[$node['id']]);
            } else {
                $this->nodes[$node['id']]['children'] = json_encode(array());
            }
        }
        
        // Tính toán personal_pv từ invoice
        $month = date("m") - 1;
        $date = date("Y-" . sprintf("%02d", $month) . "-") . "26 00:00:00";
        $sql = "
            SELECT id_user, SUM(total_money) FROM invoices
            WHERE created > '$date' AND status = 1
            GROUP BY id_user
        ";
        $pvs = $this->controller->Member->query($sql);
        foreach($pvs as $pv){
            if (isset($this->nodes[$pv['invoices']['id_user']])){
                $this->nodes[$pv['invoices']['id_user']]['personal_pv'] = $pv[0]['SUM(total_money)']/20000;
            }
        }
        
        // Tính toán số max pv của 1 invoice trong 1 lần mua để phục vụ xét level
        $month = date("m") - 1;
        $date = date("Y-" . sprintf("%02d", $month) . "-") . "26 00:00:00";
        $sql = "
            SELECT id_user, MAX(total_money) FROM invoices
            WHERE created > '$date' AND status = 1
            GROUP BY id_user
        ";
        $pvs = $this->controller->Member->query($sql);
        foreach($pvs as $pv){
            if (isset($this->nodes[$pv['invoices']['id_user']])){
                $this->nodes[$pv['invoices']['id_user']]['max_pv_per_invoice'] = $pv[0]['MAX(total_money)']/20000;
            }
        }
    }

    /**
     * Tính toán thu nhập nhóm trên toàn hệ thống
     */
    function calculateGroupPv(){
        // Doanh số toàn công ty
        $this->totalPv = 0;
        $this->nodeIdsByOrder = array();

        // Lấy danh sách tree theo thứ tự duyệt cây chiều rộng
        $queued = array();
        foreach ($this->nodes as $node){
            if ($node['parent_id'] == 0){
                array_push($queued, $node);
            }
        }
        while (count($queued)>0){
            $node = array_shift($queued);
            $this->nodeIdsByOrder[] = $node['id'];
             
            $childNodes = $this->getChildNodes($node);
            foreach ($childNodes as $childNode){
                array_push($queued, $childNode);
            }
        }

        // Tính group pv theo thuật toán quy hoạch động
        $i = count($this->nodeIdsByOrder) - 1;
        while ($i>=0){
            $node = &$this->nodes[$this->nodeIdsByOrder[$i]];
            $pv = $node['personal_pv'];
            $childNodes = $this->getChildNodes($node);
            $numOfChildren = 0;
            foreach ($childNodes as $childNode){
                $pv += $childNode['group_pv'];
                $numOfChildren += $childNode['num_of_children'];
            }
            
            // Tính toán số con
            if (isset($node['num_of_children'])){
                $this->nodes[$this->nodeIdsByOrder[$i]]['num_of_children'] += count($childNodes) + $numOfChildren;
            } else {
                $this->nodes[$this->nodeIdsByOrder[$i]]['num_of_children'] = count($childNodes) + $numOfChildren;
            }
            
            // Tính toán group_pv
            $node['group_pv'] = $pv;
            // Doanh số toàn công ty
            if ($node['parent_id']==0){
                $this->totalPv += $pv;
            }
            $i -= 1;
        }
    }

    /**
     *
     * Tính toán hoa hồng trực tiếp cho toàn hệ thống
     */
    function calculateDirectCommission(){
        foreach ($this->nodes as &$node){
            if (isset($this->directCommission[$node['tmp_levels']])){
                $this->nodes[$node['id']]['direct_commission'] = $this->directCommission[$node['tmp_levels']]*$node['personal_pv']/100;
                $this->nodes[$node['id']]['commission'] = $this->directCommission[$node['tmp_levels']]*$node['personal_pv']/100;;
            } else {
                $this->nodes[$node['id']]['direct_commission'] = 0;
                $this->nodes[$node['id']]['commission'] = 0;
            }
        }
    }

    /**
     *
     * Tính toán hoa hồng trực tiếp cho 1 member
     */
    function calculateDirectCommissionForOneMember($node){
        $node = $this->nodes[$node['id']];
        
        if (isset($this->directCommission[$this->nodes[$node['id']]['tmp_levels']])){
            $this->nodes[$node['id']]['direct_commission'] = $this->directCommission[$node['tmp_levels']]*$node['personal_pv']/100;
            $this->nodes[$node['id']]['commission'] = $this->directCommission[$node['tmp_levels']]*$node['personal_pv']/100;;
        } else {
            $this->nodes[$node['id']]['direct_commission'] = 0;
            $this->nodes[$node['id']]['commission'] = 0;
        }
    }

    /**
     * Tính toán hoa hồng gián tiếp cho toàn hệ thống
     */
    function calculateIndirectCommission(){
        foreach ($this->nodes as &$node){
            // Chỉ tính khi đủ điều kiện thành tích cá nhân
            $this->nodes[$node['id']]['missing_personal_pv'] = 0;
            if (isset($this->personalAccumulation[$node['tmp_levels']]) && $node['personal_pv'] >= $this->personalAccumulation[$node['tmp_levels']]){
                $indirectCommission = 0;
                $childNodes = $this->getChildNodes($node);
                foreach ($childNodes as $childNode){
                    if (isset($this->indirectCommission[$node['tmp_levels']][$childNode['tmp_levels']])){
                        $indirectCommission += $this->indirectCommission[$node['tmp_levels']][$childNode['tmp_levels']]*$childNode['group_pv']/100;
                    }
                }
                $this->nodes[$node['id']]['indirect_commission'] = $indirectCommission;
                $this->nodes[$node['id']]['commission'] += $indirectCommission;
            } else {
                $this->nodes[$node['id']]['indirect_commission'] = 0;
                if (isset($this->personalAccumulation[$node['tmp_levels']])){
                    $this->nodes[$node['id']]['missing_personal_pv'] = $this->personalAccumulation[$node['tmp_levels']] - $node['personal_pv'];
                }
            }
        }
    }
    
    /**
     * Tính toán hoa hồng gián tiếp cho 1 member
     */
    function calculateIndirectCommissionForOneMember($node){
        $node = $this->nodes[$node['id']];
        $this->nodes[$node['id']]['missing_personal_pv'] = 0;
        // Chỉ tính khi đủ điều kiện thành tích cá nhân
        if (isset($this->personalAccumulation[$node['tmp_levels']]) && $node['personal_pv'] >= $this->personalAccumulation[$node['tmp_levels']]){
            $indirectCommission = 0;
            $childNodes = $this->getChildNodes($node);
            foreach ($childNodes as $childNode){
                if (isset($this->indirectCommission[$node['tmp_levels']][$childNode['tmp_levels']])){
                    $indirectCommission += $this->indirectCommission[$node['tmp_levels']][$childNode['tmp_levels']]*$childNode['group_pv']/100;
                }
            }
            $this->nodes[$node['id']]['indirect_commission'] = $indirectCommission;
            $this->nodes[$node['id']]['commission'] += $indirectCommission;
        } else {
            $this->nodes[$node['id']]['indirect_commission'] = 0;
            if (isset($this->personalAccumulation[$node['tmp_levels']])){
                $this->nodes[$node['id']]['missing_personal_pv'] = $this->personalAccumulation[$node['tmp_levels']] - $node['personal_pv'];
            }
        }
    }
    
    /**
     * Tính toán hoa hồng lãnh đạo cho toàn hệ thống
     */
    function calculateLeadCommission(){
        foreach ($this->nodes as $node){
            $this->nodes[$node['id']]['missing_group_pv'] = 0;
            if ($node['tmp_levels']>=3){
                $this->calculateLeadCommissionForOneMember($node);
            } else {
                $this->nodes[$node['id']]['lead_commission'] = 0;
            }
        }
    }

    /**
     *
     * Tính toán hoa hồng lãnh đạo cho 1 member
     * @param $node
     */
    function calculateLeadCommissionForOneMember($node){
        $node = $this->nodes[$node['id']];
        
        // Chỉ tính khi đủ điều kiện thành tích nhóm
        if (isset($this->groupAccumulation[$node['tmp_levels']]) && $node['group_pv'] < $this->groupAccumulation[$node['tmp_levels']]){
            $this->nodes[$node['id']]['lead_commission'] = 0;
            if (isset($this->groupAccumulation[$node['tmp_levels']])){
                $this->nodes[$node['id']]['missing_group_pv'] = $this->groupAccumulation[$node['tmp_levels']] - $node['group_pv'];
            }
            return;
        }
        
        // Danh sách member cùng cấp
        $sameLevelNodes = array();

        $queued = array();
        $this->nodes[$node['id']]['tree_level'] = 0;

        $childNodes = $this->getChildNodes($node);
        foreach ($childNodes as $childNode){
            // Nếu đồng cấp thì đưa vào danh sách
            if ($childNode['tmp_levels'] == $node['tmp_levels']){
                array_push($sameLevelNodes, $childNode);
            }
            $this->nodes[$childNode['id']]['tree_level'] = 1;
            // Trường hợp member có tmp_levels lớn hơn thì không đưa vào danh sách
            if ($childNode['tmp_levels'] <= $node['tmp_levels']){
                array_push($queued, $childNode);
            }
        }

        while (count($queued)>0){
            $firstNode = array_shift($queued);
            $childNodes = $this->getChildNodes($firstNode);
            foreach ($childNodes as $childNode){
                // Nếu đồng cấp thì đưa vào danh sách
                if ($childNode['tmp_levels'] == $node['tmp_levels']){
                    array_push($sameLevelNodes, $childNode);
                }
                $this->nodes[$childNode['id']]['tree_level'] = $this->nodes[$firstNode['id']]['tree_level'] + 1;
                // Trường hợp member có tmp_levels lớn hơn thì không đưa vào danh sách
                if ($childNode['tmp_levels'] <= $node['tmp_levels']){
                    array_push($queued, $childNode);
                }
            }
        }

        // Duyệt lại danh sách lấy hoa hồng lãnh đạo
        $i = 0;
        $level = 0;
        $leadCommission = 0;
        while ($i<count($sameLevelNodes)){
            if (!isset($this->leadCommission[$node['tmp_levels']][$level])) break;
            $leadCommission += $this->leadCommission[$node['tmp_levels']][$level] * $this->nodes[$sameLevelNodes[$i]['id']]['group_pv'] / 100;
            if (isset($sameLevelNodes[$i + 1]) && $this->nodes[$sameLevelNodes[$i]['id']]['tree_level']!=$this->nodes[$sameLevelNodes[$i+1]['id']]['tree_level']){
                $level += 1;
            }
            $i += 1;
        }
        $this->nodes[$node['id']]['lead_commission'] = $leadCommission;
        $this->nodes[$node['id']]['commission'] += $leadCommission;
    }

    /**
     * Tính toán hoa hồng toàn cầu cho toàn hệ thống
     */
    function calculateGlobalCommission(){
        $countGlobalMembers = array(
        7 => 0,
        8 => 0,
        9 => 0,
        10 => 0,
        11 => 0,
        12 => 0,
        13 => 0,
        14 => 0,
        );
        foreach ($this->nodes as $node){
            if (isset($countGlobalMembers[$node['tmp_levels']])) $countGlobalMembers[$node['tmp_levels']] += 1;
        };

        $globalCommissions = array();
        foreach ($countGlobalMembers as $level => $countGlobalMember){
            if ($countGlobalMember>0){
                $globalCommissions[$level] = $this->totalPv * $this->globalCommission[$level]/$countGlobalMember;
            }
        }

        foreach ($this->nodes as $node){
            if (isset($globalCommissions[$node['tmp_levels']])){
                $this->nodes[$node['id']]['global_commission'] = $globalCommissions[$node['tmp_levels']];
                $this->nodes[$node['id']]['commission'] += $globalCommissions[$node['tmp_levels']];
            } else {
                $this->nodes[$node['id']]['global_commission'] = 0;
            }   
        };
    }

    /**
     * Tính toán hoa hồng toàn cầu cho 1 member
     */
    function calculateGlobalCommissionForOneMember($node){
        $node = $this->nodes[$node['id']];
        
        $countGlobalMembers = array(
        7 => 0,
        8 => 0,
        9 => 0,
        10 => 0,
        11 => 0,
        12 => 0,
        13 => 0,
        14 => 0,
        );
        foreach ($this->nodes as $nodeItem){
            if (isset($countGlobalMembers[$nodeItem['tmp_levels']])) $countGlobalMembers[$nodeItem['tmp_levels']] += 1;
        };

        $globalCommissions = array();
        foreach ($countGlobalMembers as $level => $countGlobalMember){
            if ($countGlobalMember>0){
                $globalCommissions[$level] = $this->totalPv * $this->globalCommission[$level]/$countGlobalMember;
            }
        }
        if (isset($globalCommissions[$node['tmp_levels']])){
            $this->nodes[$node['id']]['global_commission'] = $globalCommissions[$node['tmp_levels']];
            $this->nodes[$node['id']]['commission'] += $globalCommissions[$node['tmp_levels']];
        } else {
            $this->nodes[$node['id']]['global_commission'] = 0;
        }
    }
    
    /**
     * Tính toán thuế thu nhập cá nhân cho toàn hệ thống
     */
    function calculatePersonalIncomeTax(){
        foreach ($this->nodes as $node){
            if (empty($this->nodes[$node['id']]['deal'])){
                if (!empty($this->nodes[$node['id']]['tax_code'])){
                    $this->nodes[$node['id']]['personal_income_tax'] = $this->personalIncomeTax($this->nodes[$node['id']]['commission']);
                } else {
                    $this->nodes[$node['id']]['personal_income_tax'] = $this->nodes[$node['id']]['commission'] * 20 / 100;
                }
            } else {
                $this->nodes[$node['id']]['personal_income_tax'] = 0;
            }
        };
    }
    
    /**
     * Tính toán thuế thu nhập cá nhân cho 1 member
     */
    function calculatePersonalIncomeTaxForOneMember($node){
        if (empty($this->nodes[$node['id']]['deal'])){
            if (!empty($this->nodes[$node['id']]['tax_code'])){
                $this->nodes[$node['id']]['personal_income_tax'] = $this->nodes[$node['id']]['commission'] * 10 / 100;
            } else {
                $this->nodes[$node['id']]['personal_income_tax'] = $this->nodes[$node['id']]['commission'] * 20 / 100;
            }
        } else {
            $this->nodes[$node['id']]['personal_income_tax'] = 0;
        }
    }
    
    /**
     * Hàm tính toán thuế thu nhập
     * @param $value
     */
    function personalIncomeTax($value){
        $maxLevel = 1;
        foreach ($this->personalIncomeTax as $key=>$tax){
            if ($value > $tax['min'] && $value <= $tax['max']){
                $maxLevel = $key;
                break;
            }
        }
        $tax = ($value - $this->personalIncomeTax[$maxLevel]['min']) * $this->personalIncomeTax[$maxLevel]['tax'] / 100;
        for($i=$maxLevel-1; $i>0; $i--){
            $tax += ($this->personalIncomeTax[$i]['max'] - $this->personalIncomeTax[$i]['min']) * $this->personalIncomeTax[$i]['tax'] / 100;
        }
        return $tax;
    }
    
    /**
     * Hiển thị toàn bộ hệ thống
     */
    function printAllTree(){
        foreach ($this->nodes as $node){
            if ($node['parent_id'] == 0){
                $this->recursive($node);
            }
        }
    }

    /**
     * Hiển thị cây cấp dưới cho member
     */
    function printTree($node){
        ob_start();
        $node = $this->nodes[$node['id']];
        $childNodes = $this->getChildNodes($node);
        if (count($childNodes)>0){
            echo "<ul>";
            foreach ($childNodes as $childNode){
                $this->recursive($childNode);
            }
            echo "</ul>";
        }
        return ob_get_clean();
    }
    
    
    /**
     * Đệ quy hiển thị cho tree 
     */
    function recursive($node){
        $childNodes = $this->getChildNodes($node);

        if (count($childNodes)>0){
            echo "<li><span class='folder'>";
            $this->printNode($node);
            echo "</span>";
            echo "<ul>";
            foreach ($childNodes as $childNode){
                $this->recursive($childNode);
            }
            echo "</ul>";
            echo "</li>";
        } else {
            echo "<li><span class='file'>";
            $this->printNode($node);
            echo "</span>";
            echo "<ul>";
            foreach ($childNodes as $childNode){
                $this->recursive($childNode);
            }
            echo "</ul>";
            echo "</li>";           
        }
    }

    /**
     * Hiện thị tree
     */
    function printNode($node){
        echo "<a href='#'>" . $node['name'] . "</a>&nbsp;";
        if (isset($node['user'])) echo $node['user'];
        if (isset($node['tmp_levels'])) echo "-" . $this->namesOfLevel[$node['tmp_levels']];
        if (isset($node['num_of_children'])) echo "-HVC:" . $node['num_of_children'];
        if (isset($node['group_pv'])) echo "-" . $node['group_pv'] . "pv";
    }
    
    /**
     * Hiển thị debug toàn bộ hệ thống
     */
    function _printAllTree(){
        foreach ($this->nodes as $node){
            if ($node['parent_id'] == 0){
                $this->_recursive($node);
            }
        }
    }
    
    /**
     * Hiển thị node cho debug
     */
    function _printNode($node){
        
        echo $this->nodes[$node['id']]['name'];
        echo "||" . $this->nodes[$node['id']]['id'];
        if (isset($this->nodes[$node['id']]['levels'])) echo "||levels:" . $this->nodes[$node['id']]['levels'];
        if (isset($this->nodes[$node['id']]['personal_pv'])) echo "||personal_pv:" . $this->nodes[$node['id']]['personal_pv'];
        if (isset($this->personalAccumulation[$this->nodes[$node['id']]['levels']])) echo "||personal_accumulation:" . $this->personalAccumulation[$this->nodes[$node['id']]['levels']];
        if (isset($this->nodes[$node['id']]['group_pv'])) echo "||group_pv:" . $this->nodes[$node['id']]['group_pv'];
        if (isset($this->nodes[$node['id']]['tmp_levels'])) echo "||tmp_levels::" . $this->nodes[$node['id']]['tmp_levels'];
        if (isset($this->nodes[$node['id']]['missing_personal_pv'])) echo "||missing_personal_pv::" . $this->nodes[$node['id']]['missing_personal_pv'];
        if (isset($this->nodes[$node['id']]['missing_group_pv'])) echo "||missing_group_pv:" . $this->nodes[$node['id']]['missing_group_pv'];
//        if (isset($this->nodes[$node['id']]['direct_commission'])) echo "||direct_commission::" . $this->nodes[$node['id']]['direct_commission'];
//        if (isset($this->nodes[$node['id']]['indirect_commission'])) echo "||indirect_commission:" . $this->nodes[$node['id']]['indirect_commission'];
//        if (isset($this->nodes[$node['id']]['lead_commission'])) echo "||lead_commission:" . $this->nodes[$node['id']]['lead_commission'];
//        if (isset($this->nodes[$node['id']]['global_commission'])) echo "||global_commission:" . $this->nodes[$node['id']]['global_commission'];
//        if (isset($this->nodes[$node['id']]['levels'])) echo "||levels:" . $this->nodes[$node['id']]['levels'];
//        if (isset($this->nodes[$node['id']]['tree_level'])) echo "||tree_level:" . $this->nodes[$node['id']]['tree_level'];
//        if (isset($this->nodes[$node['id']]['commission'])) echo "||commission:" . $this->nodes[$node['id']]['commission'];
        echo '<br/>';
    }
    
    /**
     * Đệ quy debug 
     */
    function _recursive($node){
        $childNodes = $this->getChildNodes($node);

        if (count($childNodes)>0){
            echo "<li><span class='folder'>";
            $this->_printNode($node);
            echo "</span>";
            echo "<ul>";
            foreach ($childNodes as $childNode){
                $this->_recursive($childNode);
            }
            echo "</ul>";
            echo "</li>";
        } else {
            echo "<li><span class='file'>";
            $this->_printNode($node);
            echo "</span>";
            echo "<ul>";
            foreach ($childNodes as $childNode){
                $this->_recursive($childNode);
            }
            echo "</ul>";
            echo "</li>";           
        }
    }

    /**
     *
     * Enter description here ...
     * @param $node
     */
    function getChildNodes($node){
        $childNodes = array();
        
        $childNodeIds = json_decode($this->nodes[$node['id']]['children'], true);
        foreach ($childNodeIds as $childNodeId){
            $childNodes[] = $this->nodes[$childNodeId];
        }
        
        return $childNodes;
    }

    /**
     * Tỉ lệ phần trăm hoa hồng trực tiếp
     * $directCommission[x] hoa hồng trực tiếp cấp x
     */
    var $directCommission;

    /**
     * Tỉ lệ hoa hồng gián tiếp
     * $indirectCommission[x][y] hoa hồng gián tiếp cấp x->y
     */
    var $indirectCommission;

    /**
     * Tỉ lệ hoa hồng lãnh đạo
     * $indirectCommission[x][y] hoa hồng gián tiếp cấp x->y
     */
    var $leadCommission;

    /**
     * Tỉ lệ hoa hồng toàn cầu
     * $globalCommission[x]hoa hồng toàn cầu cấp x
     */
    var $globalCommission;

    /**
     * Tích lũy cá nhân / tháng
     */
    var $personalAccumulation = array(
    0=>0,1=>0,2=>10,3=>30,4=>60,5=>100,6=>150,7=>150,8=>150,9=>150,10=>150,11=>150,12=>150,13=>150,14=>150,15=>150,
    );

    /**
     * Tích lũy nhóm / tháng
     */
    var $groupAccumulation = array(
    0=>0,1=>0,2=>0,3=>600,4=>1200,5=>1500,6=>2500,7=>2500,8=>2500,9=>2500,10=>2500,11=>2500,12=>2500,13=>2500,14=>2500,15=>2500,
    );
    
    /**
     * Tên cấp bậc
     */
    var $namesOfLevel = array(
        0 =>"Leader dự bị",
        1=>"Leader 1",
        2=>"Leader 2",
        3=>"Leader 3",
        4=>"Leader 4",
        5=>"Leader 5",
        6=>"Leader 6",
        7=>"Vip Leader 1",
        8=>"Vip Leader 2",
        9=>"Vip Leader 3",
        10=>"Saphia Leader",
        11=>"Ruby Leader",
        12=>"Diamond Leader",
        13=>"Super Leader",
        14=>"General Leader",
        15=>"Forever Leader",
    );
    
    /**
     * Phân trăm thuế thu nhập cá nhân
     */
    var $personalIncomeTax = array(
        1 => array('min' => 0, 'max' => 4000000, 'tax' => 0),
        2 => array('min' =>  4000000, 'max' =>  6000000, 'tax' => 5),
        3 => array('min' =>  6000000, 'max' =>  9000000, 'tax' => 10),
        4 => array('min' =>  9000000, 'max' => 14000000, 'tax' => 15),
        5 => array('min' => 14000000, 'max' => 24000000, 'tax' => 20),
        6 => array('min' => 24000000, 'max' => 44000000, 'tax' => 25),
        7 => array('min' => 44000000, 'max' => 84000000, 'tax' => 30),
        8 => array('min' => 84000000, 'max' => PHP_INT_MAX, 'tax' => 35),
    );
}
?>